package br.com.bankai.koby.service.impl;

import java.security.InvalidParameterException;
import java.util.List;

import javax.persistence.NoResultException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import br.com.bankai.koby.repository.dom.DomPessoa;
import br.com.bankai.koby.repository.dom.DomPessoa.DomStatusPessoaFisica;
import br.com.bankai.koby.repository.entity.Usuario;
import br.com.bankai.koby.repository.entity.simple.UsuarioSimple;
import br.com.bankai.koby.repository.impl.UsuarioRepository;
import br.com.bankai.koby.service.exception.AlreadyExistsException;
import br.com.bankai.koby.service.exception.NoResultFoundException;
import br.com.bankai.koby.service.exception.PinRegisteredException;
import br.com.bankai.koby.service.exception.UserAuthenticationException;
import br.com.bankai.koby.service.util.EmailService;
import br.com.bankai.koby.service.util.EncryptHelper;
import br.com.bankai.koby.service.util.PasswordService;

/**
 * 
 * @author Leonardo
 *
 */
@Service("usuarioService")
public class UsuarioService {

	@Autowired
	private UsuarioRepository repository;

	@Autowired
	private PessoaFisicaService pessoaFisicaService;

	@Autowired
	private PasswordService passwordService;
	@Autowired
	private EmailService emailService;

	public List<UsuarioSimple> search(UsuarioSimple entity, List<String> papeis) {

		return repository.search(entity, papeis);
	}
	
	public Usuario autentica(String cpf, String password) throws NoResultFoundException, UserAuthenticationException, PinRegisteredException {
		Usuario usuario = null;
		
		try {
			
			usuario = find(new Usuario(null, cpf, null));
		} catch (NoResultException e) {
			throw new NoResultFoundException("Usuario nao encontrado");
		}

		if (usuario.getStatus() != DomStatusPessoaFisica.PENDENTE) {
			throw new PinRegisteredException("Primeiro acesso ja realizado");
		}

		String encryptedPassword = EncryptHelper.encrypt(password);
	
		if (!encryptedPassword.equals(usuario.getSenhaAcesso())) {
			throw new UserAuthenticationException("Senha incorreta");
		}

		return usuario;
	}
	
	public void primeiroAcesso(Long id, String password) throws NoResultFoundException, AlreadyExistsException, InvalidParameterException {
		Usuario usuario = null;
		try {
			usuario = find(new Usuario(id, null, null));
		} catch (NoResultException e) {
			throw new NoResultFoundException("Usuario nao encontrado");
		}

		usuario.setStatus(DomPessoa.DomStatusPessoaFisica.ATIVO);
		usuario.setSenhaAcesso(EncryptHelper.encrypt(password));

		save(usuario);
	}
	
	public UsuarioSimple find(UsuarioSimple entity) throws NoResultFoundException {
		try {
			return repository.find(entity);
		} catch (NoResultException e) {
			throw new NoResultFoundException("Pessoa nao encontrada");
		}
	}
	
	
	public Usuario find(Usuario entity) throws NoResultFoundException {
		try {
			return repository.find(entity);
		} catch (NoResultException e) {
			throw new NoResultFoundException("Pessoa nao encontrada");
		}
	}

	public void save(Usuario entity) throws AlreadyExistsException {
		boolean including = null == entity.getId();

		String senha = null;
		if (including) {
			senha = passwordService.generate((Usuario) entity);
		}

		pessoaFisicaService.save(entity);

		if (including) {
			emailService.sendUsuarioPassword((Usuario) entity, senha);
		}
	}

	public void resetPassword(Usuario entity) throws NoResultFoundException {
		Usuario usuario = (Usuario) pessoaFisicaService.find(entity);

		passwordService.generateAndSend(usuario);
        //JOptionPane.showMessageDialog(null, "o usuario foi"+usuario.getNome()+"e a senha eh "+usuario.getSenhaAcesso());
		repository.update(usuario);
	}

	public void updateSenhaAcesso(Long idPessoa, String senhaAcesso) {
		repository.updateSenhaAcesso(idPessoa, senhaAcesso);
	}

	public void updateQuantidadeTentativas(Long idPessoa, int quantidadeTentativas) {
		repository.updateQuantidadeTentativas(idPessoa, quantidadeTentativas);
	}

	public void updateStatus(Long idPessoa, char status) {
		repository.updateStatus(idPessoa, status);
	}
}